package com.chengyi.serialport.demo.activity

import android.text.InputType
import android.widget.TextView
import androidx.databinding.ObservableField
import androidx.lifecycle.MutableLiveData
import com.chengyi.serialboard.sdk.RyPcbWeight5SerialPortUtil
import com.chengyi.serialboard.sdk.SerialPortOptions
import com.chengyi.serialport.demo.R
import com.chengyi.serialport.demo.databinding.ActivityRyPcbWeight5DemoBinding
import com.chengyi.serialport.demo.utils.ExpirableFunction2
import com.hjq.toast.Toaster
import com.wyj.utils.QMUIDialogHelper
import me.goldze.mvvmhabit.binding.command.BindingAction

class ActivityRyPcbWeight5Demo : BaseActivity<ActivityRyPcbWeight5DemoBinding, ActivityRyPcbWeight5Demo.ViewModel>() {
    override fun getLayoutRes(): Int = R.layout.activity_ry_pcb_weight5_demo
    override fun initViews() {
        initBar(binding.myTopBar)
    }

    override fun onDestroy(binding: ActivityRyPcbWeight5DemoBinding?) {
        vm.close()
    }

    class ViewModel : BaseSerialPortViewModel<RyPcbWeight5SerialPortUtil>() {
        val deviceNum = MutableLiveData("16")
        private val deviceNumValue: Byte? get() = deviceNum.value?.toByteOrNull()
        override val serialportPath = ObservableField("/dev/ttyS0")
        override val baudrate = ObservableField("115200")
        override val textHex: TextView?
            get() = uiChangeLiveData.getBinding<ActivityRyPcbWeight5DemoBinding>()?.textHex
        val famaWeight = MutableLiveData<String>()
        val gravityNumber = MutableLiveData<String>()
        private val readWeightCallback = ExpirableFunction2<Byte, RyPcbWeight5SerialPortUtil.RyPcbWeight5SerialData>(2000)
        private val executeCallback = ExpirableFunction2<Byte, RyPcbWeight5SerialPortUtil.RyPcbWeight5SerialData>(2000)
        override fun createSerialPortUtil(path: String, baudrate: Int): RyPcbWeight5SerialPortUtil? {
            return RyPcbWeight5SerialPortUtil(
                SerialPortOptions().path(path).baudrate(baudrate).txConnect(SerialPortOptions.RX).rxConnect(SerialPortOptions.TX).useGND(true).mode(SerialPortOptions.MODE_TTL),
                object : RyPcbWeight5SerialPortUtil.Callback {
                    override fun onSendHexCallback(sendHex: String?) {
                        sendHex?.let(this@ViewModel::onSerialPortSendCallback)
                    }

                    override fun onReceiveHexCallback(receiveHex: String?) {
                        receiveHex?.let(this@ViewModel::onSerialPortReceiveCallback)
                    }


                    override fun onReadWeightCallback(deviceNum: Byte, e: RyPcbWeight5SerialPortUtil.RyPcbWeight5SerialData) {
                        readWeightCallback.getUnExpired().forEach {
                            it.invoke(deviceNum, e)
                        }
                    }

                    override fun onExecuteCallback(deviceNum: Byte, e: RyPcbWeight5SerialPortUtil.RyPcbWeight5SerialData) {
                        executeCallback.getUnExpired().forEach {
                            it.invoke(deviceNum, e)
                        }
                    }
                }
            )
        }

        val onReadClick = BindingAction {
            val deviceNum = deviceNumValue ?: return@BindingAction
            runSerialPortCommand {
                readWeightCallback.add { mDeviceNum, e ->
                    if (mDeviceNum == deviceNum) {
                        val sb = StringBuilder()
                        sb.append(" 秤1:${e.weight1}g   秤2:${e.weight2}g   秤3:${e.weight3}g   秤4:${e.weight4}g   秤5:${e.weight5}g\t\t")
                        sb.append(" 秤1AD:${e.ad1}   秤2AD:${e.ad2}   秤3AD:${e.ad3}   秤4AD:${e.ad4}   秤5AD:${e.ad5}")
                        onSerialPortAnalysisCallback(sb.toString())
                        true
                    } else {
                        false
                    }
                }
                it.readGravityInfo(deviceNum)
            }
        }
        val onSetZeroClick = BindingAction {
            val deviceNum = deviceNumValue ?: return@BindingAction
            val gravityNumber = gravityNumber.value?.toByteOrNull()
            if (gravityNumber == null) {
                Toaster.show("请输入正确的编号")
                return@BindingAction
            }
            runSerialPortCommand {
                executeCallback.add { mDeviceNum, e ->
                    if (mDeviceNum == deviceNum) {
                        onSerialPortAnalysisCallback("秤${gravityNumber}置零${if (e.writeValue?.toByte() == gravityNumber) "成功" else "失败"}")
                        true
                    } else {
                        false
                    }
                }
                it.setZero(deviceNum, gravityNumber)
            }
        }
        val onSetFamaClick = BindingAction {
            val deviceNum = deviceNumValue ?: return@BindingAction
            val famaWeight = famaWeight.value?.toIntOrNull()
            if (famaWeight == null || famaWeight < 1) {
                Toaster.show("请输入正确的砝码重量")
                return@BindingAction
            }
            runSerialPortCommand {
                executeCallback.add { mDeviceNum, e ->
                    if (mDeviceNum == deviceNum) {
                        onSerialPortAnalysisCallback("设置${if (e.writeValue == famaWeight) "成功" else "失败"}  砝码重量为:${famaWeight}g")
                        true
                    } else {
                        false
                    }
                }
                it.setFamaWeight(deviceNum, famaWeight)
            }
        }
        val onValidateGravityClick = BindingAction {
            val deviceNum = deviceNumValue ?: return@BindingAction
            val gravityNumber = gravityNumber.value?.toByteOrNull()
            if (gravityNumber == null) {
                Toaster.show("请输入正确的编号")
                return@BindingAction
            }
            runSerialPortCommand {
                executeCallback.add { mDeviceNum, e ->
                    if (mDeviceNum == deviceNum) {
                        onSerialPortAnalysisCallback("秤${gravityNumber}标定${if (e.writeValue?.toByte() == gravityNumber) "成功" else "失败"}")
                        true
                    } else {
                        false
                    }
                }
                it.validateGravity(deviceNum, gravityNumber)
            }
        }

        val onSetDeviceNumClick = BindingAction {
            val deviceNumValue = deviceNumValue
            if (deviceNumValue == null) {
                Toaster.show("请输入有效的设备地址")
                return@BindingAction
            }
            QMUIDialogHelper.createEditDialog(uiChangeLiveData.getContext() ?: return@BindingAction, "提示", InputType.TYPE_CLASS_NUMBER, "请输入新地址", "", onEditListener = object : QMUIDialogHelper.OnEditListener {
                override fun onEditListener(text: String) {
                    val newDeviceNum = text.toByteOrNull()
                    if (newDeviceNum == null) {
                        Toaster.show("请输入正确的设备地址")
                        return
                    }
                    runSerialPortCommand {
                        executeCallback.add { mDeviceNum, e ->
                            if (mDeviceNum == deviceNumValue) {
                                if (e.writeValue?.toByte() == newDeviceNum) {
                                    onSerialPortAnalysisCallback("设置成功，设置前地址:${deviceNumValue},设置后地址:${newDeviceNum}")
                                    deviceNum.postValue("$newDeviceNum")
                                } else {
                                    onSerialPortAnalysisCallback("设置失败")
                                }
                                true
                            } else {
                                false
                            }
                        }
                        it.setDeviceNum(deviceNumValue, newDeviceNum)
                    }
                }
            }).show()
        }
    }
}